﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bes.Swsp.ToolBox
{
  public abstract class TransitionNode : NodePoint
  {
    protected TransitionNode()
      : base()
    {
    }

    protected TransitionNode(int id)
      : base(id)
    {
    }

    /// <summary>
    /// The next downstream transition node this node drains to. Can be null.
    /// </summary>
    public TransitionNode DownstreamTransition
    {
      get
      {
        HashSet<NodePoint> tracedNodes = new HashSet<NodePoint>();
        return _GetDownstreamTransition(this, tracedNodes);
      }
    }

    private TransitionNode _GetDownstreamTransition(NodePoint node, HashSet<NodePoint> tracedNodes)
    {
      if (tracedNodes.Contains(node))
      {
        return null;
      }
      else
      {
        tracedNodes.Add(node);
      }

      if (node.DownstreamConveyance != null && node.DownstreamConveyance.DownstreamNode != null)
      {
        TransitionNode transition = node.DownstreamConveyance.DownstreamNode as TransitionNode;
        if (transition != null)
        {
          return transition;
        }
        else
        {
          if (node.Enabled)
          {
            return _GetDownstreamTransition(node.DownstreamConveyance.DownstreamNode, tracedNodes);
          }
          else
          {
            return null;
          }
        }
      }
      else
      {
        return null;
      }
    }

    /// <summary>
    /// All adjacent upstream transition nodes that drain to this node. Can be empty.
    /// </summary>
    public ICollection<TransitionNode> UpstreamTransitions
    {
      get
      {
        HashSet<NodePoint> tracedNodes = new HashSet<NodePoint>();
        HashSet<TransitionNode> upTransitions = new HashSet<TransitionNode>();
        _GetUpstreamTransitions(this, this is OutletNode, upTransitions, tracedNodes);
        return upTransitions;
      }
    }

    private void _GetUpstreamTransitions(NodePoint node, bool subsurface, HashSet<TransitionNode> upTransitions, HashSet<NodePoint> tracedNodes)
    {
      if (tracedNodes.Contains(node))
      {
        return;
      }
      else
      {
        tracedNodes.Add(node);
      }

      if (node.UpstreamConveyances != null)
      {
        foreach (Conveyance conveyance in node.UpstreamConveyances)
        {
          if (conveyance.Enabled && conveyance.IsSubSurface == subsurface)
          {
            if (conveyance.UpstreamNode != null)
            {
              TransitionNode item = conveyance.UpstreamNode as TransitionNode;
              if (item != null)
              {
                upTransitions.Add(item);
              }

              if (conveyance.UpstreamNode.Enabled)
              {
                _GetUpstreamTransitions(conveyance.UpstreamNode, subsurface, upTransitions, tracedNodes);
              }
            }
          }
        }
      }
    }

    public override string ToString()
    {
      return string.Format("Transition {0}", this.ID);
    }
  }
}
